#     TextLocutor
#     Copyright (C) 2009  Jose Ignacio Naranjo Hernandez (joseignacio.naranjo@gmail.com)

#     This program is free software: you can redistribute it and/or modify
#     it under the terms of the GNU Affero General Public License as
#     published by the Free Software Foundation, either version 3 of the
#     License, or (at your option) any later version.

#     This program is distributed in the hope that it will be useful,
#     but WITHOUT ANY WARRANTY; without even the implied warranty of
#     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#     GNU Affero General Public License for more details.

#     You should have received a copy of the GNU Affero General Public License
#     along with this program.  If not, see <http://www.gnu.org/licenses/>.

import logging
from google.appengine.ext import db
from datetime import date, timedelta
from core.models import CoreUser
from football_scores.exceptions import *

MAX_TEAMS_ALLOWED = 10

# Datastore of teams
class Team(db.Model):
    name = db.StringProperty(required=True)

    def users(self):
        return (x.user for x in self.userteamproperties_set)


class League(db.Model):
    name = db.StringProperty(required=True)
    teams = db.ListProperty(db.Key)


class Country(db.Model):
    name = db.StringProperty(required=True)
    leagues = db.ListProperty(db.Key)


# Class to be able to add 'relationship properties'
# It is needed to allow some configurable options such as being
# notified in all goals or just at the end of the match.
class UserTeamProperties(db.Model):
    coreuser = db.ReferenceProperty(CoreUser, required=True)
    team = db.ReferenceProperty(Team, required=True)
    # if true just send the final score
    only_fscore = db.BooleanProperty(default=False)
    # if false just send the goal and no scorer
    scorer = db.BooleanProperty(default=True)

    @staticmethod
    def add_user_team(coreuser, team_str, only_fscore=False, scorer=True):
        # user is a reference, but team is just the string
        teams = coreuser.userteamproperties_set

        if teams.count(10) == MAX_TEAMS_ALLOWED:
            raise TeamsExceededError
        else:
            team = Team.all().filter('name =', team_str).get()
            if not team:
                raise TeamNotExists
            else:
                # look for the team in the teams already selected
                for t in teams:
                    # TODO: Use id key
                    if t.team.name == team.name:
                        raise TeamSelectedError    
                utprop = UserTeamProperties(coreuser=coreuser, 
                                            team=team, 
                                            only_fscore=only_fscore, 
                                            scorer=scorer)
                utprop.put()
                return utprop

    @staticmethod
    def _delete(coreuser, team_str):
        team = Team.all().filter('name =', team_str).get()
        if not team:
            raise TeamNotExists

        teams = coreuser.userteamproperties_set

        for t in teams:
            # TODO: Use id key
            if t.team.name == team.name:
                t.delete()
                return
        raise TeamNotFound


class Match(db.Model):
    home = db.ReferenceProperty(Team, collection_name="matchhome_set")
    home_str = db.StringProperty()   # Faster queries!
    visitor = db.ReferenceProperty(Team, collection_name="matchvisitor_set")
    visitor_str = db.StringProperty()   # Faster queries!
    date = db.DateProperty()
    score = db.StringProperty()
    last_scorer = db.StringProperty()
    # extra_time = db.StringPropery(default=False)

    @staticmethod
    def get_or_insert(home_str, visitor_str, score=None):
        match = Match.all().filter('home_str =', home_str).get()
        if not match:
            home = Team.all().filter('name =', home_str).get()
            visitor = Team.all().filter('name =', visitor_str).get()
            match = Match(home=home,
                          home_str=home_str,
                          visitor=visitor,
                          visitor_str=visitor_str, 
                          date=date.today(),
                          score=score,
                          last_scorer='')
            match.put()
            logging.debug("New match: %s - %s" % (home_str, visitor_str))
        else:
            # check the date. If the date is more than one day different, 'reset' the match
            if (date.today() - match.date) > timedelta(days=1):
                visitor = Team.all().filter('name =', visitor_str).get()
                match.last_scorer = ''
                match.visitor_str = visitor_str
                match.visitor = visitor
                match.date = date.today()
                match.score = score
                match.put()
                logging.debug("New match reset: %s - %s" % (home_str, visitor_str))
        return match

    def is_new_goal(self, score):
        # A new goal is considered if the number of goals of any team increase.
        if self.score is None:
            return True
        elif len(self.score) <= 1:
            return True
        else:
            home_new, visitor_new = score.split('-')
            home_db, visitor_db = self.score.split('-')
            return (home_new > home_db) or (visitor_new > visitor_db)

    def is_last_goal(self, score):
        if self.score is None:
            return True
        elif len(self.score) <= 1:
            return True
        else:
            home_new, visitor_new = score.split('-')
            home_db, visitor_db = self.score.split('-')
            return (home_new == home_db) and (visitor_new == visitor_db)

def del_user_db(coreuser):
    utproperties = coreuser.userteamproperties_set
    db.delete(utproperties)


